using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Admin.NET.Application;
using Admin.NET.Application.Entity.Business;
using Admin.NET.Application.Enums;
using Admin.NET.Application.Excel;
using Admin.NET.Application.Service.Collector.Dto;
using Admin.NET.Application.Util;
using Admin.NET.Core;
using Furion;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using Mapster;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using SqlSugar;

/// <summary>
/// 采集器2服务
/// </summary>
[ApiDescriptionSettings(new string[] { "业务应用" }, Order = 100)]
public class CollectorService : IDynamicApiController, ITransient, IPrivateDependency
{
	private readonly SqlSugarRepository<Collector> _rep;

	private readonly SqlSugarRepository<ElectricMeter> _repmeter;

	public CollectorService(SqlSugarRepository<Collector> rep, SqlSugarRepository<ElectricMeter> repmeter)
	{
		_rep = rep;
		_repmeter = repmeter;
	}

	/// <summary>
	/// 设备导出
	/// </summary>
	/// <param name="input"></param>
	/// <returns></returns>
	[HttpPost("/collector/pageexcel")]
	public async Task<IActionResult> ExportDevice([FromQuery] CollectorInput input)
	{
		ISugarQueryable<Collector> query = _rep.Context.Queryable<Collector>().WhereIF(!string.IsNullOrWhiteSpace(input.Name), (Collector u) => u.Name.Contains(input.Name.Trim())).WhereIF(!string.IsNullOrWhiteSpace(input.Imei), (Collector u) => u.Imei.Contains(input.Imei.Trim()));
		List<CollectorOutPut> info = await query.Select((Collector u) => new CollectorOutPut
		{
			Status = u.Status,
			TenantId = u.TenantId,
			CreateTime = u.CreateTime,
			CreateUserId = u.CreateUserId,
			Id = u.Id,
			Imei = u.Imei,
			IsDelete = u.IsDelete,
			LastOnlineTime = u.LastOnlineTime,
			MeterCount = (from s4 in SqlFunc.Subqueryable<ElectricMeter>()
				where s4.CollectorId == (long?)u.Id
				select s4).Count(),
			Name = u.Name,
			Remark = u.Remark,
			UpdateTime = u.UpdateTime,
			UpdateUserId = u.UpdateUserId,
			IssuedStatus = u.IssuedStatus
		}).OrderBuilder(input).ToListAsync();
		string str = "采集网关-" + DateTime.Now.ToString("yyyy-MM-dd");
		List<string> column = new List<string>();
		List<string> title = new List<string>();
		column.AddRange(new string[5] { "Imei", "Name", "MeterCount", "Remark", "CreateTime" });
		title.AddRange(new string[5] { "序列号", "设备名称", "绑定电表数", "备注", "创建日期" });
		MemoryStream memery = ExportToExcel.ExportToList(info.ToArray(), str, str, column.ToArray(), title.ToArray());
		App.HttpContext.Response.ContentType = "application/vnd.ms-excel";
		byte[] aa = memery.ToArray();
		return new FileStreamResult(new MemoryStream(aa), "application/octet-stream")
		{
			FileDownloadName = str + ".xlsx"
		};
	}

	/// <summary>
	/// 上传文件 导入设备
	/// </summary>
	/// <param name="file"></param>
	/// <param name="path"></param>
	/// <returns></returns>
	[HttpPost("/collector/uploadpdf")]
	public async Task UploadFile([Required] IFormFile file, string path = "")
	{
		try
		{
			ExcelUtil excelUtil = new ExcelUtil();
			List<AddCollectorInput> list = excelUtil.ExcelToList<AddCollectorInput>(file, new Dictionary<string, string>
			{
				{ "序列号", "Imei" },
				{ "名称", "Name" },
				{ "备注", "Remark" }
			});
			if (list.Where((AddCollectorInput u) => string.IsNullOrWhiteSpace(u.Imei) || string.IsNullOrWhiteSpace(u.Name)).Any())
			{
				throw Oops.Oh("当前序列号名称不能为空");
			}
			List<string> imeilist = list.Select((AddCollectorInput i) => i.Imei).ToList();
			Collector eleModel = await (from u in _rep.Context.Queryable<Collector>()
				where imeilist.Contains(u.Imei)
				select u).FirstAsync();
			if (eleModel != null)
			{
				throw Oops.Oh("当前表序列号已存在" + eleModel.Imei);
			}
			string disImei = (from u in imeilist
				group u by u into u
				select new
				{
					count = u.Count(),
					sn = u.Key
				} into u
				where u.count > 1
				select u).FirstOrDefault()?.sn;
			if (!string.IsNullOrEmpty(disImei))
			{
				throw Oops.Oh("当前表序列号存在重复" + disImei);
			}
			List<Collector> entity = list.Adapt<List<Collector>>();
			await _rep.InsertRangeAsync(entity);
		}
		catch (Exception)
		{
			throw;
		}
	}

	/// <summary>
	/// 导出列表excel
	/// </summary>
	/// <returns></returns>
	[HttpPost("/collector/templeteexcel")]
	public async Task<IActionResult> Templeteexcel()
	{
		string str = "采集网关-" + DateTime.Now.ToString("yyyy-MM-dd");
		List<string> list = new List<string> { "序列号", "名称", "备注" };
		Dictionary<string, List<string>> dic = new Dictionary<string, List<string>>();
		ExcelUtil excelUtil = new ExcelUtil();
		MemoryStream stream = excelUtil.GetTemplate(list, dic, str);
		return new FileStreamResult(new MemoryStream(stream.ToArray()), "application/octet-stream")
		{
			FileDownloadName = str + ".xlsx"
		};
	}

	/// <summary>
	/// 分页查询采集器2
	/// </summary>
	/// <param name="input"></param>
	/// <returns></returns>
	[HttpGet("/collector/page")]
	public async Task<dynamic> Page([FromQuery] CollectorInput input)
	{
		ISugarQueryable<Collector> query = (from u in _rep.Context.Queryable<Collector>()
			where u.Type == input.Type
			select u).WhereIF(!string.IsNullOrWhiteSpace(input.Name), (Collector u) => u.Name.Contains(input.Name.Trim())).WhereIF(!string.IsNullOrWhiteSpace(input.Imei), (Collector u) => u.Imei.Contains(input.Imei.Trim()));
		ISugarQueryable<CollectorOutPut> info = query.Select((Collector u) => new CollectorOutPut
		{
			Status = u.Status,
			TenantId = u.TenantId,
			CreateTime = u.CreateTime,
			CreateUserId = u.CreateUserId,
			Id = u.Id,
			Imei = u.Imei,
			IsDelete = u.IsDelete,
			LastOnlineTime = u.LastOnlineTime,
			MeterCount = (from s4 in SqlFunc.Subqueryable<ElectricMeter>()
				where s4.CollectorId == (long?)u.Id
				select s4).Count() + (from s4 in SqlFunc.Subqueryable<WaterDevice>()
				where s4.CollectorId == (long?)u.Id
				select s4).Count(),
			Name = u.Name,
			Remark = u.Remark,
			UpdateTime = u.UpdateTime,
			UpdateUserId = u.UpdateUserId,
			IssuedStatus = u.IssuedStatus,
			Type = u.Type
		}).OrderBuilder(input);
		return await info.ToPagedListAsync(input.Page, input.PageSize);
	}

	/// <summary>
	/// 增加采集器2
	/// </summary>
	/// <param name="input"></param>
	/// <returns></returns>
	[HttpPost("/collector/add")]
	public async Task Add(AddCollectorInput input)
	{
		Collector entity = input.Adapt<Collector>();
		if (await _rep.Context.Queryable<Collector>().ClearFilter().AnyAsync((Collector u) => u.Imei == entity.Imei))
		{
			throw Oops.Oh(ErrorCodeEnum.R2002);
		}
		await _rep.InsertAsync(entity);
	}

	/// <summary>
	/// 删除采集器2
	/// </summary>
	/// <param name="input"></param>
	/// <returns></returns>
	[HttpPost("/collector/delete")]
	public async Task Delete(BaseIdInput input)
	{
		Collector entity = await _rep.GetFirstAsync((Collector u) => u.Id == input.Id);
		if (await _rep.Context.Queryable<ElectricMeter>().AnyAsync((ElectricMeter u) => u.CollectorId == (long?)entity.Id))
		{
			throw Oops.Oh(ErrorCodeEnum.D1007);
		}
		await _rep.DeleteAsync(entity);
	}

	/// <summary>
	/// 删除采集器2批量
	/// </summary>
	/// <param name="input"></param>
	/// <returns></returns>
	[HttpPost("/collector/deleteAny")]
	public async Task DeleteAny(List<BaseIdInput> input)
	{
		List<long> ids = input.Select((BaseIdInput u) => u.Id).ToList();
		List<Collector> entity = await _rep.GetListAsync((Collector u) => ids.Contains(u.Id));
		if (await _rep.Context.Queryable<ElectricMeter>().AnyAsync((ElectricMeter u) => ids.Contains(u.CollectorId.Value)))
		{
			throw Oops.Oh(ErrorCodeEnum.D1007);
		}
		await _rep.DeleteAsync(entity);
	}

	/// <summary>
	/// 下发数据
	/// </summary>
	/// <param name="input"></param>
	/// <returns></returns>
	[HttpPost("/collector/issuedCollector")]
	public async Task IssuedCollector(IssuedCollectorMeter input)
	{
		Collector collector = await (from u in _rep.Context.Queryable<Collector>()
			where u.Id == input.Id
			select u).FirstAsync();
		if (collector == null)
		{
			throw Oops.Oh(ErrorCodeEnum.xg1002);
		}
		new List<string>();
		List<string> meterListAddr = (input.IsWater ? (await (from u in _rep.Context.Queryable<WaterDevice>()
			where u.CollectorId == (long?)input.Id
			select u.LowAddr).ToListAsync()) : (await (from u in _rep.Context.Queryable<ElectricMeter>()
			where u.CollectorId == (long?)input.Id
			select u.LowAddr).ToListAsync()));
		(IAggrementPlugin, BrandModel) plugin = AggrementPluginUtil.GetPlugin((ElectricMeter)null, isDTU: true);
		var (pluginService, _) = plugin;
		_ = plugin.Item2;
		var (success, body) = pluginService.Configuration(collector.Imei, meterListAddr);
		if (!success)
		{
			if (!input.IsWater)
			{
				await (from u in _rep.Context.Updateable<Collector>().SetColumns((Collector u) => u.IssuedStatus == 3)
					where u.Id == collector.Id
					select u).ExecuteCommandAsync();
				await (from u in _rep.Context.Updateable<ElectricMeter>().SetColumns((ElectricMeter u) => u.IssuedStatus == 3)
					where u.CollectorId == (long?)collector.Id
					select u).ExecuteCommandAsync();
			}
			else
			{
				await (from u in _rep.Context.Updateable<Collector>().SetColumns((Collector u) => u.IssuedStatus == 3)
					where u.Id == collector.Id
					select u).ExecuteCommandAsync();
			}
			throw Oops.Oh(ErrorCodeEnumEx.X1002);
		}
		string[] arr = JsonConvert.DeserializeObject<string[]>(body);
		if (meterListAddr.Where((string u) => !arr.Contains(u)).Any())
		{
			if (!input.IsWater)
			{
				await (from u in _rep.Context.Updateable<Collector>().SetColumns((Collector u) => u.IssuedStatus == 3)
					where u.Id == collector.Id
					select u).ExecuteCommandAsync();
				await (from u in _rep.Context.Updateable<ElectricMeter>().SetColumns((ElectricMeter u) => u.IssuedStatus == 3)
					where u.CollectorId == (long?)collector.Id
					select u).ExecuteCommandAsync();
				throw Oops.Oh(ErrorCodeEnumEx.X1001);
			}
			await (from u in _rep.Context.Updateable<Collector>().SetColumns((Collector u) => u.IssuedStatus == 3)
				where u.Id == collector.Id
				select u).ExecuteCommandAsync();
		}
		else if (!input.IsWater)
		{
			await (from u in _rep.Context.Updateable<ElectricMeter>().SetColumns((ElectricMeter u) => u.IssuedStatus == 2)
				where u.CollectorId == (long?)collector.Id
				select u).ExecuteCommandAsync();
			await (from u in _rep.Context.Updateable<Collector>().SetColumns((Collector u) => u.IssuedStatus == 2).SetColumns((Collector u) => u.Status == 1)
				where u.Id == collector.Id
				select u).ExecuteCommandAsync();
		}
		else
		{
			await (from u in _rep.Context.Updateable<Collector>().SetColumns((Collector u) => u.IssuedStatus == 2).SetColumns((Collector u) => u.Status == 1)
				where u.Id == collector.Id
				select u).ExecuteCommandAsync();
		}
	}

	/// <summary>
	/// 更新采集器2
	/// </summary>
	/// <param name="input"></param>
	/// <returns></returns>
	[HttpPost("/collector/edit")]
	public async Task Update(UpdateCollectorInput input)
	{
		Collector entity = input.Adapt<Collector>();
		if (await _rep.IsAnyAsync((Collector u) => u.Imei == entity.Imei && u.Id != entity.Id))
		{
			throw Oops.Oh(ErrorCodeEnum.R2002);
		}
		await _rep.Context.Updateable(entity).UpdateColumns((Collector u) => new { u.Name, u.Imei, u.Remark, u.IssuedStatus }).ExecuteCommandAsync();
	}

	/// <summary>
	/// 查询
	/// </summary>
	/// <param name="id"></param>
	/// <returns></returns>
	[HttpGet("/collector/getCollectorMeter")]
	public async Task<dynamic> GetCollectorMeter(long id)
	{
		List<BindMeterOutput> list = new List<BindMeterOutput>();
		List<long> keyList = new List<long>();
		if (await (from u in _rep.Context.Queryable<Collector>()
			where u.Id == id
			select u).AnyAsync())
		{
			var meterInfo = await (from u in _rep.Context.Queryable<ElectricMeter>()
				where u.CollectorId == (long?)id || (u.CollectorId == null && u.ProtocolType == 1)
				select new { u.Id, u.Sn, u.CollectorId, u.Name }).ToListAsync();
			list = meterInfo.Select(u => new BindMeterOutput
			{
				Disabled = false,
				Key = u.Id,
				Label = u.Sn + "-" + u.Name
			}).ToList();
			keyList = (from u in meterInfo
				where u.CollectorId == id
				select u.Id).ToList();
		}
		return new
		{
			LeftValue = list,
			rightValue = keyList
		};
	}

	/// <summary>
	/// 查询
	/// </summary>
	/// <param name="id"></param>
	/// <returns></returns>
	[HttpGet("/collector/getCollectorWater")]
	public async Task<dynamic> GetCollectorWater(long id)
	{
		List<BindMeterOutput> list = new List<BindMeterOutput>();
		List<long> keyList = new List<long>();
		if (await (from u in _rep.Context.Queryable<Collector>()
			where u.Id == id
			select u).AnyAsync())
		{
			var meterInfo = await (from u in _rep.Context.Queryable<WaterDevice>()
				where u.CollectorId == (long?)id || (u.CollectorId == null && u.ProtocolType == 1)
				select new { u.Id, u.Sn, u.CollectorId, u.WaterName }).ToListAsync();
			list = meterInfo.Select(u => new BindMeterOutput
			{
				Disabled = false,
				Key = u.Id,
				Label = u.Sn + "-" + u.WaterName
			}).ToList();
			keyList = (from u in meterInfo
				where u.CollectorId == id
				select u.Id).ToList();
		}
		return new
		{
			LeftValue = list,
			rightValue = keyList
		};
	}

	/// <summary>
	/// 绑定
	/// </summary>
	/// <param name="meter"></param>
	/// <returns></returns>
	[HttpPost("/collector/bindMeter")]
	public async Task BindMeter(BindMeterInput meter)
	{
		List<ElectricMeter> result = await (from u in _rep.Context.Queryable<ElectricMeter>()
			where u.CollectorId == (long?)meter.CollectorId || meter.Id.Contains(u.Id)
			select u).ToListAsync();
		result.ForEach(delegate(ElectricMeter u)
		{
			if (meter.Id.Contains(u.Id))
			{
				u.CollectorId = meter.CollectorId;
			}
			else
			{
				u.CollectorId = null;
			}
		});
		_rep.Context.Updateable(result).UpdateColumns((ElectricMeter u) => new { u.CollectorId }).ExecuteCommand();
	}

	/// <summary>
	/// 绑定水表
	/// </summary>
	/// <param name="meter"></param>
	/// <returns></returns>
	[HttpPost("/collector/bindwater")]
	public async Task BindWater(BindMeterInput meter)
	{
		List<WaterDevice> result = await (from u in _rep.Context.Queryable<WaterDevice>()
			where u.CollectorId == (long?)meter.CollectorId || meter.Id.Contains(u.Id)
			select u).ToListAsync();
		result.ForEach(delegate(WaterDevice u)
		{
			if (meter.Id.Contains(u.Id))
			{
				u.CollectorId = meter.CollectorId;
			}
			else
			{
				u.CollectorId = null;
			}
		});
		_rep.Context.Updateable(result).UpdateColumns((WaterDevice u) => new { u.CollectorId }).ExecuteCommand();
	}
}
